package container

import (
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/typedefault"
	"codejy/utils"
	"strconv"
)

// key 实例地址,value 值
type TypeBytes struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
	bytes       []byte
}

// 创建实例
func (a *TypeBytes) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	bytes := &TypeBytes{
		bytes:       []byte{},
		Addr:        addr,
		ThreadStore: threadStore,
	}
	store.AddTypeDefaultInstanceStore(threadStore, a.GetTypeName(), addr, bytes)
}

func (a *TypeBytes) GetData() interface{} {
	return a.bytes
}

func (a *TypeBytes) ParameterProcessing(parameter []string) []string {
	return parameter
}

func (a *TypeBytes) ToStr() string {
	//遍历字节数组,拼接成[]
	str := "["
	for i := range a.bytes {
		str += strconv.Itoa(int(a.bytes[i])) + ","
	}
	str = str[:len(str)-1] + "]"
	return a.GetTypeName() + ":" + str
}

// 字节填充
func (a *TypeBytes) BytePadding(size int) string {
	padding := utils.BytePadding(a.bytes, size)
	//返回填充后的新字节地址
	return TransitionBytes(padding, a.ThreadStore)
}

// 还原字节填充
func (a *TypeBytes) UnBytePadding() string {
	unPadding := utils.UnBytePadding(a.bytes)
	//返回填充后的新字节地址
	return TransitionBytes(unPadding, a.ThreadStore)
}

// 获取字节长度
func (a *TypeBytes) GetBytesLen() string {
	return strconv.Itoa(len(a.bytes))
}

// 获取真实字节长度
func (a *TypeBytes) GetRealBytesLen() string {
	length := utils.GetActualBytesLength(a.bytes)
	return strconv.Itoa(length)
}

// 获取真实字节
func (a *TypeBytes) GetAddrRealBytes() string {
	actualBytes := utils.GetActualBytes(a.bytes)
	return TransitionBytes(actualBytes, a.ThreadStore)
}

// 截取范围数据
func (a *TypeBytes) SubRange(startIndex, endIndex string) string {
	if startIndex != "" && endIndex == "" {
		start, _ := strconv.Atoi(startIndex)
		if start < 0 || start >= len(a.bytes) {
			panic("起始索引超出范围")
		}
		slice := a.bytes[start:]
		return TransitionBytes(slice, a.ThreadStore)
	}
	if startIndex != "" && endIndex != "" {
		start, _ := strconv.Atoi(startIndex)
		end, _ := strconv.Atoi(endIndex)
		if start < 0 || start >= len(a.bytes) || end < 0 || end >= len(a.bytes) {
			panic("起始或结束索引超出范围")
		}
		slice := a.bytes[start:end]
		return TransitionBytes(slice, a.ThreadStore)
	}
	panic("参数错误,起始索引不能为空")
}

// =======================================================================下面是内部方法,不对外暴露的方法=======================================================================

func (f TypeBytes) GetDef() string {
	return `
		@CodeManual(def="new("Bytes")",des="一般不会直接创建Bytes实例,而是通过字符串转换或者文件读取")
		type  Bytes{
			def init{
				core&CreateTypeDefault()
			}
			@CodeManual(def="toStr()",des="字节转字符串,bytes.toStr(?)")
			def toStr{
				to core&ToStr()
			}

			@CodeManual(def="padding($1)",des="填充字节,bytes.padding(10)")
			def padding{
				to core&BytePadding($1)
			}
			@CodeManual(def="unPadding()",des="还原填充的字节,bytes.padding()")
			def unPadding{
				to core&UnBytePadding()
			}

			@CodeManual(def="size()",des="获取字节长度,bytes.size()")
			def size{
				to core&GetBytesLen()
			}

			@CodeManual(def="realSize()",des="获取真实字节长度,就是不计算结尾的0")
			def realSize{
				to core&GetRealBytesLen()
			}

			@CodeManual(def="real()",des="获取真实字节,就是去掉结0")
			def real{
				to core&GetAddrRealBytes()
			}

			@CodeManual(def="range($1,$2)",des="截取List返回新的List(起始下标从0开始, 结束下标从1开始),例:bytes.range(1,3)")
			def range{
				to core&SubRange($1,$2)
			}

		}
	`
}

func init() {
	typedefault.RegisterTypeDefault(&TypeBytes{})
	globalfunc.RegisterFuncAll("TransitionBytes", TransitionBytes)
}

func (f *TypeBytes) GetTypeName() string {
	return "Bytes"
}

// 将bytes转换为简易语言中的bytes ,并返回实例地址 (内部方法,不对外暴露)
func TransitionBytes(bytes []byte, threadStore *structdef.ThreadStore) string {

	addr := typedefault.TypeDefaultNewInstance("Bytes", threadStore)
	newBytes := &TypeBytes{
		Addr:        addr,
		ThreadStore: threadStore,
		bytes:       bytes,
	}
	store.AddTypeDefaultInstanceStore(threadStore, "Bytes", addr, newBytes)
	return addr
}
